home *** CD-ROM | disk | FTP | other *** search
/ The Programmer Disk / The Programmer Disk (Microforum).iso / xpro / c3 / pro6 / hrt.c < prev    next >
C/C++ Source or Header  |  1991-02-06  |  5KB  |  170 lines

  1. /*Demonstrates the code to use the 8253/8354 timer chip as a
  2.   microsecond-resolution general purpose system timer.    Also shows
  3.   how to disable the Ctrl-C code that DOS uses to abort a program,
  4.   which is necessary when we have installed interrupts or otherwise
  5.   changed things that must be made right before we exit.
  6.   (C) 1991 Bruce Ackerman, Convivia Software.*/
  7.  
  8. #pragma inline
  9.  
  10. #include <conio.h>
  11. #include <bios.h>
  12.  
  13. static void far* oldCint;
  14.  
  15. /*Installs a simple control-C handler, which ignores the request, thus
  16.   disabling Ctrl-C.  The installation of this handler will prevent Ctrl-C
  17.   or Ctrl-Break from aborting your program, though those silly "^C" things
  18.   will still be sent to your screen, and a keystroke may still appear in
  19.   the queue, when Ctrl-C is pressed.*/
  20. void ctrlC_install(void)
  21. {
  22. asm mov ax,3523h
  23. asm int 21h        /*DOS get vector call*/
  24. asm mov word ptr oldCint,bx
  25. asm mov word ptr oldCint+2,es
  26. asm push ds
  27. asm mov dx,offset intruptC
  28. asm mov ax,cs
  29. asm mov ds,ax
  30. asm mov ax,2523h
  31. asm int 21h        /*set int 23 vector*/
  32. asm pop ds
  33. asm jmp short retn
  34.  
  35. /*Here is the Ctrl-C handler itself*/
  36. asm intruptC:
  37. asm iret
  38.  
  39. retn: ;
  40. }
  41.  
  42. void ctrlC_uninstall(void)
  43. {
  44. asm push ds
  45. asm lds dx,oldCint
  46. asm mov ax,2523h
  47. asm int 21h        /*DOS reset the vector*/
  48. asm pop ds
  49. }
  50.  
  51. /*This function is the first one to call before using the 8253 high-resolution
  52.   timer. It sets the 8253 channel 0 to use mode 2, which works just as well as
  53.   the usual mode 3 for the purpose of generating periodic interrupts (it just
  54.   outputs an asymmetric pulse train), but which has the advantage that the
  55.   count value only counts down once per tick so we can read it unambiguously.
  56.   Because the bios tick count resets at midnight, causing great complexity in
  57.   our using it for accurate intervals, we eliminate it altogether and use our
  58.   own interrupt handler, which this function installs on int 1C. Therefore
  59.   the companion function hrt_close() MUST be called before the program exits!*/
  60. void hrt_open(void)
  61. {
  62. asm mov al,034h
  63. asm out 43h,al        /*control reg: mode 2*/
  64. asm xor al,al
  65. asm out 40h,al        /*count value 0 (65536)*/
  66. asm out 40h,al
  67.  
  68. asm mov ax,351Ch
  69. asm int 21h        /*DOS get vector call*/
  70. asm mov word ptr cs:oldvect,bx
  71. asm mov word ptr cs:oldvect+2,es
  72.  
  73. /*install one of our handlers, which one depending on whether the old handler
  74.   was just an IRET or if it did anything more. If it was just IRET, we save
  75.   time by not chaining back to it*/
  76. asm mov dx,offset intrupt1
  77. asm cmp byte ptr es:[bx],0CFh    /*CFh is the IRET opcode*/
  78. asm je use1
  79. asm mov dx,offset intrupt2
  80. use1:
  81. asm push ds
  82. asm mov ax,cs
  83. asm mov ds,ax
  84. asm mov ax,251Ch
  85. asm int 21h        /*set int 23 vector*/
  86. asm pop ds
  87. asm jmp short retn
  88.  
  89. /*Here are the interrupt handlers themselves*/
  90. asm oldvect dd 0    /*storage for the old 1C vector*/
  91. asm tickcnt dw 0    /*the 16-bit tick counter*/
  92.  
  93. asm intrupt1:
  94. asm inc cs:tickcnt
  95. asm iret        /*do our own return*/
  96.  
  97. asm intrupt2:
  98. asm inc cs:tickcnt
  99. asm jmp dword ptr cs:oldvect /*chain to the old handler*/
  100.  
  101. retn: ;
  102. }
  103.  
  104. unsigned long hrt_count;  /*the 32-bit time, made public for convenience*/
  105.  
  106. /*Here is the function which reads our 1.19318 MHz timer, assuming that
  107.   we have called hrt_open() beforehand to set it up.*/
  108. unsigned long hrt_read(void)
  109. {
  110. asm mov bx,cs:tickcnt    /*get initial tick reading*/
  111.  
  112. asm mov al,06h
  113. asm out 43h,al        /*latch the count value*/
  114. asm in al,40h        /*read LS byte*/
  115. asm mov ah,al
  116. asm in al,40h        /*read MS byte*/
  117. asm xchg al,ah        /*put them where they belong*/
  118. asm not ax
  119. asm inc ax        /*convert it so it counts up from 0, not down from 0*/
  120.  
  121. asm mov cx,cs:tickcnt
  122. asm cmp bx,cx
  123. asm je retn        /*if bios counter didn't change, we're done*/
  124. asm cmp ax,8000h    /*decide which to use based on whether 8253 count*/
  125. asm jb retn        /*was above or below its midpoint*/
  126. asm mov cx,bx
  127.  
  128. retn:
  129. asm mov word ptr hrt_count,ax
  130. asm mov word ptr hrt_count+2,cx
  131. return hrt_count;
  132. }
  133.  
  134. /*This function MUST be called before the program exits, after all use of the
  135.   high-resolution timer is completed, to uninstall our interrupt handler from
  136.   the 1C vector*/
  137. void hrt_close(void)
  138. {
  139. asm mov al,036h
  140. asm out 43h,al          /*control reg: mode 3*/
  141. asm xor al,al
  142. asm out 40h,al          /*count value 0 (65536)*/
  143. asm out 40h,al
  144.  
  145. asm push ds
  146. asm lds dx,cs:oldvect
  147. asm test dx,dx          /*if dx is 0, ours was never installed*/
  148. asm jz skipit
  149. asm mov ax,251Ch
  150. asm int 21h             /*DOS reset the vector*/
  151. skipit: asm pop ds
  152. }
  153.  
  154. void main()
  155. {
  156. clrscr();
  157. cprintf("\n\n\n\n     1.19318 MHz timer:");
  158.  
  159. ctrlC_install();
  160. hrt_open();        /*set up the 8253 for our use*/
  161. while (!bioskey(1)) {
  162.     gotoxy(9,8);
  163.     cprintf("%10lu", hrt_read());
  164. }
  165. hrt_close();        /*put the 8253 back to normal*/
  166. ctrlC_uninstall();
  167. cprintf("\n\n\rFinished...\n");
  168. }
  169.  
  170.